package client;

import interfacePaxos.Constant;
import interfacePaxos.PaxosRemote;

import java.io.BufferedReader;
import java.io.Console;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

public class LockClient implements Runnable {
  private List<PaxosRemote> my_servers;
  private SecureRandom sr;
  private static int lock_num;
  private static boolean lock_status;

  private static final String ADDRESSFILE = "config.txt";

  public LockClient(List<PaxosRemote> the_servers) {
    my_servers = the_servers;
    sr = new SecureRandom();
    System.out.println("Servers loaded: " + my_servers.size());
  }

  /**
   * @param args
   *          the command line arguments
   * @throws IOException
   */
  public static void main(String[] args) throws NotBoundException, IOException {
    BufferedReader br = new BufferedReader(new FileReader(ADDRESSFILE));

    List<PaxosRemote> nodes = new ArrayList<PaxosRemote>();

    String line = br.readLine();
    System.out.println("File loaded: " + line);
    String[] hosts = line.split(",");

    for (String h : hosts) {
      System.out.println("entered loop with string: " + h);
      Registry registry = LocateRegistry.getRegistry(h, Constant.port);
      System.out.println("registry located");
      PaxosRemote pr = (PaxosRemote) registry.lookup(Constant.RMI_ID);
      System.out.println("paxosremote found");
      nodes.add(pr);
    }
    br.close();
    LockClient client = new LockClient(nodes);
    client.serverConfig();

    Console c = System.console();
    if (c == null) {
      System.err.println("No console.");
      System.exit(1);
    }
    String input_locknum = c.readLine("Enter lock number: ");
    String input_lockstatus = c.readLine("Enter lock status: ");
    do {
      lock_num = Integer.parseInt(input_locknum);
      lock_status = Boolean.parseBoolean(input_lockstatus);
      client.request(lock_status, lock_num);
      input_locknum = c.readLine("Enter lock number (q to quit): ");
      input_lockstatus = c.readLine("Enter lock status: ");
    } while (!input_locknum.equals("q"));
  }

  public void serverConfig() throws IOException, RemoteException,
      NotBoundException {
    for (PaxosRemote r : my_servers) {
      r.setServer();
    }
    System.out.println("Server config done.");
  }

  public boolean request(boolean lock, int number) throws RemoteException,
      IOException {
    boolean result = false;
    Console c = System.console();
    String server_choice = c.readLine("Which server to query: (0-" + (my_servers.size() - 1) + "): ");
    PaxosRemote remote = my_servers.get(Integer.parseInt(server_choice));
    System.out.println("Server selected");
    result = remote.request(lock, number);
    System.out.println("Request: " + result);
    return result;
  }

  @Override
  public void run() {
    try {

      // obtain lock
      boolean lock_obtained = request(true, lock_num);
      System.out.println("Lock " + lock_num + " obtained: " + lock_obtained);

      if (lock_obtained) {
        // hold the lock (sleep) for random amount of time
        Thread.sleep(sr.nextInt(9999) + 1);

        // release lock
        boolean released = request(false, lock_num);
        System.out.println("Lock " + lock_num + " released: " + released);
      }
    } catch (Exception e) {
      // catch exception
      System.err.println(e.toString());
    }
  }
}
